package com.audaque.cloud.iqs.dbs.service.impl;

import com.audaque.cloud.iqs.dbs.enums.DBDataTypeEnum;
import com.audaque.cloud.iqs.dbs.service.DsHandler;
import com.audaque.cloud.iqs.dbs.vo.ColumnInfo;
import com.audaque.cloud.iqs.dbs.vo.DateVo;
import com.audaque.cloud.iqs.dbs.vo.TableInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * PostgreSql ，人大金仓，高斯200 都是抄袭pg，采用pg语法即可
 * @author HuangHL
 * @date 2022-10-17 16:50:29
 */
public class DsHandlerDws implements DsHandler {
    @Override
    public boolean canHander(String driveClass) {
        return driveClass.contains("postgre") || driveClass.contains("kingbase") || driveClass.contains("gauss");
    }

    @Override
    public String getTablesSql(String scheme,String user) {
        return "select TT.tablename as table_name,PGC.comment as table_comment FROM (select * from pg_tables t  where t.schemaname='"+scheme+"' and t.tableowner='"+user+"') TT "
                + "LEFT JOIN (select  c.relname as tablename,cast(obj_description(c.relfilenode,'pg_class') as varchar) as comment from pg_class c inner join pg_namespace pc on pc.oid=c.relnamespace inner join pg_user pu on pu.usesysid=c.relowner where c.relkind = 'r' and pc.nspname='"+scheme+"' and pu.usename='"+user+"'"
                + ") PGC ON TT.tablename=PGC.tablename";
    }

    @Override
    public String getColumnsSql(String scheme,String user,String tableName) {
        return "select TT.*,TT1.contype FROM (SELECT\n"
                + "                       col_description(a.attrelid,a.attnum) as comment,"
                + "                       format_type(a.atttypid,a.atttypmod) as type,       a.attname as name,"
                + "                       cast(attnotnull as varchar) as isnotnull,       a.attnum "
                + "                FROM pg_class as c  inner join pg_namespace pc on pc.oid=c.relnamespace inner join pg_user pu on pu.usesysid=c.relowner ,pg_attribute as a where c.relname = '"+tableName+"' and a.attrelid = c.oid and a.attnum>0 and pc.nspname='"+scheme+"' and pu.usename='"+user+"') TT "
                + "                LEFT JOIN ( SELECT pg_attribute.attname AS colname,pg_constraint.contype "
                + "                       FROM  pg_constraint "
                + "                                INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid "
                + "                                 INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid "
                + "                           AND pg_attribute.attnum = pg_constraint.conkey [1] "
                + "                                 INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid "
                + "                                inner join pg_namespace pc on pc.oid=pg_class.relnamespace inner join pg_user pu on pu.usesysid=pg_class.relowner "
                + "                       WHERE pg_class.relname = '"+tableName+"' AND pg_constraint.contype = 'p' "
                + "                         and pc.nspname='"+scheme+"' and pu.usename='"+user+"' "
                + "                   ) TT1 ON TT.name=TT1.colname";
    }

    @Override
    public String getSchema(String schema,String database,String username) {
        return schema;
    }

    @Override
    public List<TableInfo> listToTables(List<Map<String, Object>> list) {
        List<TableInfo> res = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Map<String, Object> map:list) {
                String tableName = null;
                String tableDesc = null;
                if(map.get("table_name") != null) {
                    tableName = map.get("table_name").toString();
                }
                if(map.get("table_comment") != null) {
                    tableDesc = map.get("table_comment").toString();
                }
                TableInfo tableInfo = new TableInfo(tableName,tableDesc);
                res.add(tableInfo);
            }
        }
        return res;
    }

    @Override
    public List<ColumnInfo> listToColumns(List<Map<String, Object>> list, String tableName) {
        List<ColumnInfo> res = new ArrayList<>();
        for (Map<String, Object> map:list) {
            String colName = null;
            String colDesc = null;
            String dataType = null;
            String length = null;
            String po = null;
            String key = "0";
            String isIfNull = "0";
            if(map.get("name") != null) {
                colName = map.get("name").toString();
            }
            if(map.get("comment") != null) {
                colDesc = map.get("comment").toString();
            }
            if(map.get("DATA_TYPE") != null) {
                dataType = map.get("DATA_TYPE").toString();
            }
            if(map.get("type") != null) {
                String typeLength = map.get("type").toString();
                if(typeLength.contains("(")) {
                    dataType = typeLength.substring(0,typeLength.indexOf("("));
                    String lp = typeLength.substring(typeLength.indexOf("(")+1,typeLength.indexOf(")"));
                    String[] lpArr = lp.split(",");
                    if(lpArr.length == 1) {
                        length = lpArr[0];
                    }
                    if(lpArr.length == 2) {
                        length = lpArr[0];
                        po = lpArr[1];
                    }
                } else {
                    dataType = typeLength;
                }
            }
            if(map.get("contype") != null) {
                String pk = map.get("contype").toString();
                if("p".equals(pk)){
                    key = "1";
                }
            }
            if(map.get("isnotnull") != null) {
                String isNull = map.get("isnotnull").toString();
                if("true".equals(isNull)){
                    isIfNull = "1";
                }
                if("false".equals(isNull)){
                    isIfNull = "0";
                }
            }
            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setTableName(tableName);
            columnInfo.setColName(colName);
            columnInfo.setColDesc(colDesc);
            columnInfo.setColType(dataType);
            if(length!=null) {
                if(length.contains(" ")) {
                    length = length.substring(0,length.indexOf(" "));
                }
                columnInfo.setColLength(Long.valueOf(length));
            }
            if(po!=null) {
                if(po.contains(" ")) {
                    po = po.substring(0,po.indexOf(" "));
                }
                columnInfo.setColPrecision(Integer.valueOf(po));
            }
            columnInfo.setKeyFlag(key);
            columnInfo.setNullable(isIfNull);
            if(map.get("attnum") != null) {
                String ordinalPosition = map.get("attnum").toString();
                columnInfo.setColSeq(Integer.valueOf(ordinalPosition));
            }
            columnInfo.setColDataType(DBDataTypeEnum.CHAR.getCode());
            if(dataType.toUpperCase().contains("BIGINT")){
                columnInfo.setColDataType(DBDataTypeEnum.NUNBER.getCode());
            }
            if(dataType.toUpperCase().contains("INT")){
                columnInfo.setColDataType(DBDataTypeEnum.NUNBER.getCode());
            }
            if(dataType.toUpperCase().contains("CHARACTER")){
                columnInfo.setColDataType(DBDataTypeEnum.CHAR.getCode());
            }
            if(dataType.toUpperCase().contains("TEXT")){
                columnInfo.setColDataType(DBDataTypeEnum.CHAR.getCode());
            }
            if(dataType.toUpperCase().contains("TIMESTAMP")){
                columnInfo.setColDataType(DBDataTypeEnum.DATATIME.getCode());
            }
            res.add(columnInfo);
        }
        return res;
    }

    @Override
    public String getPage(String sql, int pageNo,int pageSize) {
        int offset = (pageNo-1)*pageSize;
        String mysql = sql+" limit "+pageSize+" OFFSET "+offset;
        return mysql;
    }

    @Override
    public String getDateWhereSql(DateVo dateVo) {
        return "to_char("+dateVo.getCol()+",'YYYY-MM-DD')"+dateVo.getWhereTypeStr()+"'"+dateVo.getVal()+"'";
    }

    @Override
    public String prosessAs(String sql) {
        String sql1 = sql.replaceAll("`","\"");
        return sql1;
    }

    @Override
    public String sqlSpilit() {
        return "\"";
    }


}
